import sys
import os
import requests
import json
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout,
                             QHBoxLayout, QLabel, QPushButton, QFileDialog, QTextEdit,
                             QComboBox, QMessageBox, QListWidget, QProgressBar, QSplitter)
from PyQt5.QtGui import QPixmap, QImage, QPainter, QColor, QFont
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QByteArray, QBuffer
from PIL import Image, ImageFilter, ImageEnhance
import io


class ImageProcessor(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("图像处理平台")
        self.resize(1200, 800)

        # Gitee配置
        self.gitee_token = ""
        self.repo_owner = ""
        self.repo_name = ""
        self.branch = "main"

        # 初始化UI
        self.init_ui()

    def init_ui(self):
        # 创建主布局
        main_widget = QWidget()
        main_layout = QVBoxLayout(main_widget)
        self.setCentralWidget(main_widget)

        # 创建顶部导航栏
        nav_bar = QHBoxLayout()

        # 图像加载部分
        load_widget = QWidget()
        load_layout = QHBoxLayout(load_widget)
        self.load_btn = QPushButton("加载本地图像")
        self.load_btn.clicked.connect(self.load_image)
        self.save_local_btn = QPushButton("保存本地")
        self.save_local_btn.clicked.connect(self.save_local_image)
        self.upload_gitee_btn = QPushButton("上传到Gitee")
        self.upload_gitee_btn.clicked.connect(self.upload_to_gitee)

        load_layout.addWidget(self.load_btn)
        load_layout.addWidget(self.save_local_btn)
        load_layout.addWidget(self.upload_gitee_btn)

        # Gitee配置部分
        gitee_widget = QWidget()
        gitee_layout = QHBoxLayout(gitee_widget)
        self.token_input = QTextEdit()
        self.token_input.setMaximumHeight(30)
        self.token_input.setPlaceholderText("Gitee Access Token")
        self.repo_input = QTextEdit()
        self.repo_input.setMaximumHeight(30)
        self.repo_input.setPlaceholderText("仓库名")
        self.owner_input = QTextEdit()
        self.owner_input.setMaximumHeight(30)
        self.owner_input.setPlaceholderText("用户名")
        self.config_gitee_btn = QPushButton("配置Gitee")
        self.config_gitee_btn.clicked.connect(self.config_gitee)

        gitee_layout.addWidget(QLabel("Token:"))
        gitee_layout.addWidget(self.token_input)
        gitee_layout.addWidget(QLabel("用户名:"))
        gitee_layout.addWidget(self.owner_input)
        gitee_layout.addWidget(QLabel("仓库名:"))
        gitee_layout.addWidget(self.repo_input)
        gitee_layout.addWidget(self.config_gitee_btn)

        nav_bar.addWidget(load_widget)
        nav_bar.addWidget(gitee_widget)

        # 创建中央分割器
        splitter = QSplitter(Qt.Horizontal)

        # 左侧图像显示区域
        self.image_widget = QWidget()
        self.image_layout = QVBoxLayout(self.image_widget)
        self.image_label = QLabel("请加载图像")
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.setMinimumSize(400, 400)
        self.image_layout.addWidget(self.image_label)

        # 右侧处理区域
        self.process_widget = QTabWidget()

        # 滤镜选项卡
        filter_widget = QWidget()
        filter_layout = QVBoxLayout(filter_widget)
        self.filter_combo = QComboBox()
        self.filter_combo.addItems(["模糊", "锐化", "边缘检测", "浮雕", "平滑"])
        self.apply_filter_btn = QPushButton("应用滤镜")
        self.apply_filter_btn.clicked.connect(self.apply_filter)
        filter_layout.addWidget(QLabel("选择滤镜:"))
        filter_layout.addWidget(self.filter_combo)
        filter_layout.addWidget(self.apply_filter_btn)
        self.process_widget.addTab(filter_widget, "滤镜")

        # 调整选项卡
        adjust_widget = QWidget()
        adjust_layout = QVBoxLayout(adjust_widget)

        # 亮度调整
        brightness_layout = QHBoxLayout()
        brightness_layout.addWidget(QLabel("亮度:"))
        self.brightness_slider = QComboBox()
        self.brightness_slider.addItems(["0.5", "0.8", "1.0", "1.2", "1.5"])
        brightness_layout.addWidget(self.brightness_slider)

        # 对比度调整
        contrast_layout = QHBoxLayout()
        contrast_layout.addWidget(QLabel("对比度:"))
        self.contrast_slider = QComboBox()
        self.contrast_slider.addItems(["0.5", "0.8", "1.0", "1.2", "1.5"])
        contrast_layout.addWidget(self.contrast_slider)

        # 饱和度调整
        saturation_layout = QHBoxLayout()
        saturation_layout.addWidget(QLabel("饱和度:"))
        self.saturation_slider = QComboBox()
        self.saturation_slider.addItems(["0.5", "0.8", "1.0", "1.2", "1.5"])
        saturation_layout.addWidget(self.saturation_slider)

        self.apply_adjust_btn = QPushButton("应用调整")
        self.apply_adjust_btn.clicked.connect(self.apply_adjustments)

        adjust_layout.addLayout(brightness_layout)
        adjust_layout.addLayout(contrast_layout)
        adjust_layout.addLayout(saturation_layout)
        adjust_layout.addWidget(self.apply_adjust_btn)

        self.process_widget.addTab(adjust_widget, "调整")

        # Gitee文件管理选项卡
        gitee_files_widget = QWidget()
        gitee_files_layout = QVBoxLayout(gitee_files_widget)
        self.file_list = QListWidget()
        self.refresh_files_btn = QPushButton("刷新文件列表")
        self.refresh_files_btn.clicked.connect(self.refresh_file_list)
        self.download_file_btn = QPushButton("下载选中文件")
        self.download_file_btn.clicked.connect(self.download_file)

        gitee_files_layout.addWidget(self.file_list)
        gitee_files_layout.addWidget(self.refresh_files_btn)
        gitee_files_layout.addWidget(self.download_file_btn)

        self.process_widget.addTab(gitee_files_widget, "Gitee文件")

        splitter.addWidget(self.image_widget)
        splitter.addWidget(self.process_widget)
        splitter.setSizes([600, 400])

        # 底部状态栏
        self.statusBar().showMessage("就绪")
        self.progress_bar = QProgressBar()
        self.progress_bar.hide()
        self.statusBar().addPermanentWidget(self.progress_bar)

        main_layout.addLayout(nav_bar)
        main_layout.addWidget(splitter)

        # 初始化变量
        self.current_image = None
        self.current_image_path = None
        self.gitee_files = []

    def load_image(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "选择图像", "", "图像文件 (*.png *.jpg *.jpeg *.bmp)")
        if file_path:
            self.current_image_path = file_path
            self.display_image(file_path)
            self.statusBar().showMessage(f"已加载图像: {os.path.basename(file_path)}")

    def display_image(self, image_path):
        pixmap = QPixmap(image_path)
        scaled_pixmap = pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.image_label.setPixmap(scaled_pixmap)
        # 同时加载到PIL
        self.current_image = Image.open(image_path)

    def resizeEvent(self, event):
        if self.current_image_path:
            self.display_image(self.current_image_path)
        super().resizeEvent(event)

    def save_local_image(self):
        if self.current_image:
            file_path, _ = QFileDialog.getSaveFileName(self, "保存图像", "", "图像文件 (*.png *.jpg *.jpeg *.bmp)")
            if file_path:
                try:
                    self.current_image.save(file_path)
                    self.current_image_path = file_path
                    self.statusBar().showMessage(f"已保存图像: {os.path.basename(file_path)}")
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"保存图像失败: {str(e)}")

    def config_gitee(self):
        self.gitee_token = self.token_input.toPlainText().strip()
        self.repo_owner = self.owner_input.toPlainText().strip()
        self.repo_name = self.repo_input.toPlainText().strip()

        if not all([self.gitee_token, self.repo_owner, self.repo_name]):
            QMessageBox.warning(self, "警告", "请填写完整的Gitee配置信息")
            return

        # 测试配置
        self.progress_bar.show()
        self.progress_bar.setRange(0, 0)
        self.statusBar().showMessage("正在验证Gitee配置...")

        # 在单独线程中执行网络请求
        self.thread = QThread()
        self.worker = GiteeWorker(self.gitee_token, self.repo_owner, self.repo_name, "test")
        self.worker.moveToThread(self.thread)

        self.thread.started.connect(self.worker.test_config)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.result_ready.connect(self.handle_gitee_test_result)

        self.thread.start()

    def handle_gitee_test_result(self, success, message):
        self.progress_bar.hide()
        if success:
            QMessageBox.information(self, "成功", "Gitee配置验证成功")
            self.statusBar().showMessage("Gitee配置已保存")
            # 自动刷新文件列表
            self.refresh_file_list()
        else:
            QMessageBox.critical(self, "错误", f"Gitee配置验证失败: {message}")
            self.statusBar().showMessage("Gitee配置验证失败")

    def upload_to_gitee(self):
        if not self.current_image:
            QMessageBox.warning(self, "警告", "请先加载图像")
            return

        if not all([self.gitee_token, self.repo_owner, self.repo_name]):
            QMessageBox.warning(self, "警告", "请先配置Gitee信息")
            return

        # 获取文件名
        default_name = os.path.basename(self.current_image_path) if self.current_image_path else "image.png"
        file_name, ok = QFileDialog.getSaveFileName(self, "上传到Gitee", default_name, "图像文件 (*.png *.jpg *.jpeg)")

        if ok and file_name:
            file_name = os.path.basename(file_name)

            # 转换PIL图像为字节
            byte_arr = QByteArray()
            buffer = QBuffer(byte_arr)
            buffer.open(QBuffer.WriteOnly)

            # 先将PIL图像转换为QImage
            img = self.current_image.convert("RGBA")
            data = img.tobytes("raw", "RGBA")
            qimg = QImage(data, img.size[0], img.size[1], QImage.Format_RGBA8888)

            # 保存到缓冲区
            qimg.save(buffer, "PNG")

            self.progress_bar.show()
            self.progress_bar.setRange(0, 0)
            self.statusBar().showMessage(f"正在上传到Gitee: {file_name}")

            # 在单独线程中执行上传
            self.thread = QThread()
            self.worker = GiteeWorker(self.gitee_token, self.repo_owner, self.repo_name, "upload")
            self.worker.set_upload_data(file_name, byte_arr, self.branch)
            self.worker.moveToThread(self.thread)

            self.thread.started.connect(self.worker.upload_file)
            self.worker.finished.connect(self.thread.quit)
            self.worker.finished.connect(self.worker.deleteLater)
            self.thread.finished.connect(self.thread.deleteLater)
            self.worker.result_ready.connect(self.handle_gitee_upload_result)

            self.thread.start()

    def handle_gitee_upload_result(self, success, message):
        self.progress_bar.hide()
        if success:
            QMessageBox.information(self, "成功", "图像已上传到Gitee")
            self.statusBar().showMessage("上传成功")
            # 刷新文件列表
            self.refresh_file_list()
        else:
            QMessageBox.critical(self, "错误", f"上传失败: {message}")
            self.statusBar().showMessage("上传失败")

    def refresh_file_list(self):
        if not all([self.gitee_token, self.repo_owner, self.repo_name]):
            QMessageBox.warning(self, "警告", "请先配置Gitee信息")
            return

        self.file_list.clear()
        self.progress_bar.show()
        self.progress_bar.setRange(0, 0)
        self.statusBar().showMessage("正在获取Gitee文件列表...")

        # 在单独线程中执行请求
        self.thread = QThread()
        self.worker = GiteeWorker(self.gitee_token, self.repo_owner, self.repo_name, "list")
        self.worker.set_branch(self.branch)
        self.worker.moveToThread(self.thread)

        self.thread.started.connect(self.worker.list_files)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.result_ready.connect(self.handle_gitee_file_list)

        self.thread.start()

    def handle_gitee_file_list(self, success, message, files=None):
        self.progress_bar.hide()
        if success:
            self.gitee_files = files
            for file in files:
                if 'name' in file:
                    self.file_list.addItem(file['name'])
            self.statusBar().showMessage(f"已加载 {len(files)} 个文件")
        else:
            QMessageBox.critical(self, "错误", f"获取文件列表失败: {message}")
            self.statusBar().showMessage("获取文件列表失败")

    def download_file(self):
        if self.file_list.currentRow() < 0:
            QMessageBox.warning(self, "警告", "请先选择一个文件")
            return

        selected_file = self.gitee_files[self.file_list.currentRow()]

        if 'download_url' not in selected_file:
            QMessageBox.warning(self, "警告", "无法下载该文件")
            return

        file_name = selected_file['name']
        download_url = selected_file['download_url']

        self.progress_bar.show()
        self.progress_bar.setRange(0, 0)
        self.statusBar().showMessage(f"正在下载: {file_name}")

        # 在单独线程中执行下载
        self.thread = QThread()
        self.worker = GiteeWorker(self.gitee_token, self.repo_owner, self.repo_name, "download")
        self.worker.set_download_url(download_url)
        self.worker.moveToThread(self.thread)

        self.thread.started.connect(self.worker.download_file)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.result_ready.connect(self.handle_gitee_download_result)

        self.thread.start()

    def handle_gitee_download_result(self, success, message, data=None):
        self.progress_bar.hide()
        if success and data:
            file_path, _ = QFileDialog.getSaveFileName(self, "保存下载的文件", data['name'], "图像文件 (*.png *.jpg *.jpeg)")
            if file_path:
                try:
                    with open(file_path, 'wb') as f:
                        f.write(data['content'])
                    self.current_image_path = file_path
                    self.display_image(file_path)
                    self.statusBar().showMessage(f"已下载文件: {os.path.basename(file_path)}")
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"保存文件失败: {str(e)}")
        else:
            QMessageBox.critical(self, "错误", f"下载失败: {message}")
            self.statusBar().showMessage("下载失败")

    def apply_filter(self):
        if not self.current_image:
            QMessageBox.warning(self, "警告", "请先加载图像")
            return

        filter_name = self.filter_combo.currentText()
        try:
            if filter_name == "模糊":
                filtered_img = self.current_image.filter(ImageFilter.BLUR)
            elif filter_name == "锐化":
                filtered_img = self.current_image.filter(ImageFilter.SHARPEN)
            elif filter_name == "边缘检测":
                filtered_img = self.current_image.filter(ImageFilter.FIND_EDGES)
            elif filter_name == "浮雕":
                filtered_img = self.current_image.filter(ImageFilter.EMBOSS)
            elif filter_name == "平滑":
                filtered_img = self.current_image.filter(ImageFilter.SMOOTH)
            else:
                QMessageBox.warning(self, "警告", "未知滤镜")
                return

            self.current_image = filtered_img
            self.display_image_from_pil()
            self.statusBar().showMessage(f"已应用滤镜: {filter_name}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"应用滤镜失败: {str(e)}")

    def apply_adjustments(self):
        if not self.current_image:
            QMessageBox.warning(self, "警告", "请先加载图像")
            return

        try:
            # 亮度调整
            brightness_factor = float(self.brightness_slider.currentText())
            enhancer = ImageEnhance.Brightness(self.current_image)
            img = enhancer.enhance(brightness_factor)

            # 对比度调整
            contrast_factor = float(self.contrast_slider.currentText())
            enhancer = ImageEnhance.Contrast(img)
            img = enhancer.enhance(contrast_factor)

            # 饱和度调整
            saturation_factor = float(self.saturation_slider.currentText())
            enhancer = ImageEnhance.Color(img)
            img = enhancer.enhance(saturation_factor)

            self.current_image = img
            self.display_image_from_pil()
            self.statusBar().showMessage("已应用图像调整")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"应用调整失败: {str(e)}")

    def display_image_from_pil(self):
        # 将PIL图像转换为QPixmap并显示
        img = self.current_image.convert("RGBA")
        data = img.tobytes("raw", "RGBA")
        qimg = QImage(data, img.size[0], img.size[1], QImage.Format_RGBA8888)
        pixmap = QPixmap.fromImage(qimg)
        scaled_pixmap = pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.image_label.setPixmap(scaled_pixmap)


class GiteeWorker(QThread):
    result_ready = pyqtSignal(bool, str, object)
    finished = pyqtSignal()

    def __init__(self, token, owner, repo, action):
        super().__init__()
        self.token = token
        self.owner = owner
        self.repo = repo
        self.action = action
        self.branch = "main"
        self.file_name = ""
        self.file_content = None
        self.download_url = ""

    def set_branch(self, branch):
        self.branch = branch

    def set_upload_data(self, file_name, content, branch):
        self.file_name = file_name
        self.file_content = content
        self.branch = branch

    def set_download_url(self, url):
        self.download_url = url

    def test_config(self):
        try:
            url = f"https://gitee.com/api/v5/repos/{self.owner}/{self.repo}"
            headers = {"Authorization": f"token {self.token}"}
            response = requests.get(url, headers=headers)

            if response.status_code == 200:
                self.result_ready.emit(True, "验证成功")
            else:
                self.result_ready.emit(False, f"HTTP错误 {response.status_code}: {response.text}")
        except Exception as e:
            self.result_ready.emit(False, str(e))
        finally:
            self.finished.emit()

    def list_files(self):
        try:
            url = f"https://gitee.com/api/v5/repos/{self.owner}/{self.repo}/contents?ref={self.branch}"
            headers = {"Authorization": f"token {self.token}"}
            response = requests.get(url, headers=headers)

            if response.status_code == 200:
                files = response.json()
                self.result_ready.emit(True, "获取文件列表成功", files)
            else:
                self.result_ready.emit(False, f"HTTP错误 {response.status_code}: {response.text}")
        except Exception as e:
            self.result_ready.emit(False, str(e))
        finally:
            self.finished.emit()

    def upload_file(self):
        try:
            # 先检查文件是否已存在
            check_url = f"https://gitee.com/api/v5/repos/{self.owner}/{self.repo}/contents/{self.file_name}?ref={self.branch}"
            headers = {"Authorization": f"token {self.token}"}
            response = requests.get(check_url, headers=headers)

            sha = None
            if response.status_code == 200:
                sha = response.json().get('sha')

            # 准备上传数据
            import base64
            content = base64.b64encode(self.file_content.data()).decode('utf-8')

            upload_url = f"https://gitee.com/api/v5/repos/{self.owner}/{self.repo}/contents/{self.file_name}"
            data = {
                "access_token": self.token,
                "content": content,
                "message": f"Upload {self.file_name}",
                "branch": self.branch
            }

            if sha:
                data["sha"] = sha

            # 发送请求
            if sha:
                # 更新现有文件
                response = requests.put(upload_url, json=data, headers=headers)
            else:
                # 创建新文件
                response = requests.post(upload_url, json=data, headers=headers)

            if response.status_code in [200, 201]:
                self.result_ready.emit(True, "上传成功")
            else:
                self.result_ready.emit(False, f"HTTP错误 {response.status_code}: {response.text}")
        except Exception as e:
            self.result_ready.emit(False, str(e))
        finally:
            self.finished.emit()

    def download_file(self):
        try:
            headers = {"Authorization": f"token {self.token}"}
            response = requests.get(self.download_url, headers=headers)

            if response.status_code == 200:
                # 尝试从URL中提取文件名
                file_name = self.download_url.split("/")[-1]
                self.result_ready.emit(True, "下载成功", {"name": file_name, "content": response.content})
            else:
                self.result_ready.emit(False, f"HTTP错误 {response.status_code}: {response.text}")
        except Exception as e:
            self.result_ready.emit(False, str(e))
        finally:
            self.finished.emit()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    processor = ImageProcessor()
    processor.show()
    sys.exit(app.exec_())